package edu.gatech.cs2340.OregonTrail;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JOptionPane;

import java.awt.CardLayout;
import java.awt.Dimension;

import javax.swing.JPanel;

import edu.gatech.cs2340.OregonTrail.EventSystem.AtLocationEvent;
import edu.gatech.cs2340.OregonTrail.EventSystem.AtRiverEvent;
import edu.gatech.cs2340.OregonTrail.EventSystem.AtShopEvent;
import edu.gatech.cs2340.OregonTrail.EventSystem.CommCoordinator;
import edu.gatech.cs2340.OregonTrail.EventSystem.CommunicationModule;
import edu.gatech.cs2340.OregonTrail.EventSystem.GUIEvent;
import edu.gatech.cs2340.OregonTrail.EventSystem.GUIListener;
import edu.gatech.cs2340.OregonTrail.EventSystem.LoseEvent;
import edu.gatech.cs2340.OregonTrail.EventSystem.WinEvent;

import java.io.IOException;

/**
 * Main application class for Oregon Trail game. Responsible for initializing the frame, changing between
 * screens, and coordinating the GUI
 * @author Tyler Johnston
 * @version 1.0.1
 */
public class OregonTrailApp implements GUIListener {

	//Added JPanel for river crossing
	private JFrame frame;
	private JPanel cards;
	private CardLayout cl;
	private JPanel cards2;
	private CardLayout cl2;
	private ConfigurationPanel configPanel;
	private StartPanel startPanel;
	private ShopPanel shopPanel;
	private Game gameEngine;
	private CommCoordinator communicator;
	private PlayPanel playPanel;
	private MapPanel mapPanel;
	private LocationPanel locationPanel;
	private int started;
	private RiverPanel riverPanel;
	private WinPanel winPanel;
	private JFrame menuFrame;
	private JPanel menuPanel;
	private JPanel losePanel;
	@SuppressWarnings("unused")
	private GameDB gameDB;

	/**
	 * Main constructor for application class	
	 */
	public OregonTrailApp() {
		//Eclipse will complain this is never used. Leave it here for now. This is to ensure that something is always
		//pointing to a reference to avoid resets
		gameDB = GameDB.getGameDB();
		
		
		frame = new JFrame("Oregon Trail");
		cards = new JPanel(new CardLayout());
		cl = (CardLayout)(cards.getLayout());
		frame.setResizable(false);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		menuFrame = new JFrame("Game Menu");
		cards2 = new JPanel(new CardLayout());
		cl2 = (CardLayout)(cards2.getLayout());
		menuFrame.setResizable(false);
		menuFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		menuFrame.getContentPane().add(cards2);
				
		communicator = new CommunicationModule();
		communicator.AddGUIListener(this);
		gameEngine = new Game(communicator);
		configPanel = new ConfigurationPanel(gameEngine);
		winPanel = new WinPanel();
		
		try {
			shopPanel = new ShopPanel(this, communicator);
			startPanel = new StartPanel(this);
			playPanel = new PlayPanel(this, gameEngine);
			mapPanel = new MapPanel(this, gameEngine.getTrail());
		} catch (IOException e) {
			e.printStackTrace();
		}
				
		cards.add(startPanel, "Start");
		cards.add(configPanel, "Config");
		cards.add(shopPanel, "Shop");
		cards.add(playPanel, "Play");
		cards.add(mapPanel, "Map");
		cards.add(winPanel, "Win");

		started = 0;
		frame.getContentPane().add(cards);
		frame.setSize(startPanel.getPreferredSize());
		cl.show(cards, "Start");
	}

	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					OregonTrailApp window = new OregonTrailApp();
					window.frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}
		
	/**
	 * Switch the panel shown by the frame to display the configuration screen
	 */
	public void showConfigScreen(){
		frame.setSize(configPanel.getPreferredSize());
		cl.show(cards, "Config");
	}
	
	/**
	 * Switch the panel shown by the frame to display the load screen
	 */
	public void showLoadScreen(){
		JOptionPane.showMessageDialog(null,"Your game was loaded.");
		
	}

	public void showShop(){
		frame.setSize(shopPanel.getPreferredSize());
		cl.show(cards, "Shop");
	}

	public void showPlayPanel(){
		gameEngine.updatePlayPanel(playPanel);
		frame.setSize(playPanel.getPreferredSize());
		cl.show(cards, "Play");
	}
		
	public PlayPanel getPlayPanel(){
		return playPanel;
	}
	
	public void showMap(){
		mapPanel.updateMap();
		frame.setSize(mapPanel.getPreferredSize());
		cl.show(cards, "Map");
	}
	
	public void showRiverCross(){
		frame.setSize(riverPanel.getPreferredSize());
		cl.show(cards, "River Crossing");
	}
	
	public void returnFromShop(){
		if(started == 0){
			started = 1;
			gameEngine.updatePlayPanel(playPanel);
			frame.setSize(playPanel.getPreferredSize());
			cl.show(cards, "Play");
		}
		else{
			frame.setSize(locationPanel.getPreferredSize());
			cl.show(cards, "Location");
		}
	}
	
	public void showMenu(){
	
		try {
			menuPanel = new MenuPanel(this, communicator, gameEngine.getParty());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		cards2.add(menuPanel, "Menu");
		menuFrame.setSize(menuPanel.getPreferredSize());
		cl2.show(cards2, "Menu");
		menuFrame.setVisible(true);
	}
	
	@Override
	public void guiActionPerformed(GUIEvent e) {
		if (e instanceof AtLocationEvent){
			locationPanel = new LocationPanel(this, (Location)e.getSource(), communicator, gameEngine.getParty());
			cards.add(locationPanel, "Location");
			frame.setSize(locationPanel.getPreferredSize());
			cl.show(cards, "Location");
		}
		else if(e instanceof AtShopEvent){
			frame.setSize(shopPanel.getPreferredSize());
			cl.show(cards, "Shop");
		}
		else if(e instanceof AtRiverEvent){
			riverPanel = new RiverPanel(this, communicator, (River) e.getSource());
			cards.add(riverPanel, "River Crossing");
			frame.setSize(riverPanel.getPreferredSize());
			cl.show(cards,"River Crossing");
		}
		else if(e instanceof WinEvent){
			cl.show(cards, "Win");
		}
		else if(e instanceof LoseEvent){
			try {
				losePanel = new LosePanel((String) e.getSource());
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			cards.add(losePanel, "GameOver");
			frame.setSize(losePanel.getPreferredSize());
			cl.show(cards, "GameOver");
		}
	}

	public Game getGame() {
		return gameEngine;
	}
}
